// Package initialize 提供统一的服务初始化管理
package initialize

import (
	"context"
	"fmt"
	"time"

	"go.uber.org/zap"

	"yanxue_ai_go/pkg/common/config"
	"yanxue_ai_go/pkg/common/database"
	"yanxue_ai_go/pkg/common/logger"
	"yanxue_ai_go/pkg/common/mongodb"
	"yanxue_ai_go/pkg/common/redis"
)

// ServiceDependencies 定义服务可能需要的依赖项
type ServiceDependencies struct {
	Database bool
	Redis    bool
	MongoDB  bool
	Logger   bool
	Config   bool
}

// InitResult 初始化结果
type InitResult struct {
	Config  *config.Config
	Cleanup func() error
}

// Initialize 统一初始化服务依赖项
func Initialize(serviceName string, deps ServiceDependencies) (*InitResult, error) {
	var cleanupFuncs []func() error

	// 1. 加载配置（通常是第一步）
	var cfg *config.Config
	if deps.Config {
		var err error
		cfg, err = config.LoadConfig("")
		if err != nil {
			return nil, fmt.Errorf("failed to load config: %w", err)
		}
	}

	// 2. 初始化日志系统
	if deps.Logger {
		if cfg == nil {
			return nil, fmt.Errorf("logger initialization requires config to be loaded first")
		}

		if err := logger.Init(logger.Config{
			Level:  cfg.Log.Level,
			Format: cfg.Log.Format,
			Output: "stdout",
		}); err != nil {
			return nil, fmt.Errorf("failed to initialize logger: %w", err)
		}

		cleanupFuncs = append(cleanupFuncs, func() error {
			logger.Close()
			return nil
		})
		logger.Logger.Info("Service starting",
			zap.String("service", serviceName),
			zap.String("version", cfg.App.Version))
	}

	// 3. 初始化数据库
	if deps.Database {
		if cfg == nil {
			return nil, fmt.Errorf("database initialization requires config to be loaded first")
		}

		if err := database.Init(database.Config{
			Host:            cfg.Database.Host,
			Port:            cfg.Database.Port,
			User:            cfg.Database.User,
			Password:        cfg.Database.Password,
			Name:            cfg.Database.Name,
			Charset:         cfg.Database.Charset,
			MaxOpenConns:    cfg.Database.MaxOpenConns,
			MaxIdleConns:    cfg.Database.MaxIdleConns,
			ConnMaxLifetime: cfg.Database.ConnMaxLifetime,
		}); err != nil {
			// 清理已初始化的资源
			cleanup(cleanupFuncs)
			return nil, fmt.Errorf("failed to initialize database: %w", err)
		}

		cleanupFuncs = append(cleanupFuncs, database.Close)
		if deps.Logger {
			logger.Logger.Info("Database initialized successfully")
		}
	}

	// 4. TODO 暂时注掉初始化Redis
	/*if deps.Redis {
		if cfg == nil {
			return nil, fmt.Errorf("Redis initialization requires config to be loaded first")
		}

		if err := redis.Init(redis.Config{
			Host:     cfg.Redis.Host,
			Port:     cfg.Redis.Port,
			Password: cfg.Redis.Password,
			DB:       cfg.Redis.DB,
			PoolSize: cfg.Redis.PoolSize,
		}); err != nil {
			// 清理已初始化的资源
			cleanup(cleanupFuncs)
			return nil, fmt.Errorf("failed to initialize Redis: %w", err)
		}

		cleanupFuncs = append(cleanupFuncs, redis.Close)
		if deps.Logger {
			logger.Logger.Info("Redis initialized successfully")
		}
	}*/

	// 5. 初始化MongoDB（如果需要）
	if deps.MongoDB {
		if cfg == nil {
			return nil, fmt.Errorf("MongoDB initialization requires config to be loaded first")
		}

		if err := mongodb.Init(mongodb.Config{
			Host:     cfg.MongoDB.Host,
			Port:     cfg.MongoDB.Port,
			User:     cfg.MongoDB.User,
			Password: cfg.MongoDB.Password,
			Database: cfg.MongoDB.Database,
		}); err != nil {
			// 清理已初始化的资源
			cleanup(cleanupFuncs)
			return nil, fmt.Errorf("failed to initialize MongoDB: %w", err)
		}

		cleanupFuncs = append(cleanupFuncs, mongodb.Close)
		if deps.Logger {
			logger.Logger.Info("MongoDB initialized successfully")
		}
	}

	// 返回结果和清理函数
	return &InitResult{
		Config: cfg,
		Cleanup: func() error {
			return cleanup(cleanupFuncs)
		},
	}, nil
}

// cleanup 执行清理操作
func cleanup(cleanupFuncs []func() error) error {
	var lastErr error

	// 反向执行清理函数（后初始化的先清理）
	for i := len(cleanupFuncs) - 1; i >= 0; i-- {
		if err := cleanupFuncs[i](); err != nil {
			lastErr = err
		}
	}

	return lastErr
}

// HealthCheck 执行所有已初始化组件的健康检查
func HealthCheck(deps ServiceDependencies) error {
	if deps.Database {
		if err := database.HealthCheck(); err != nil {
			return fmt.Errorf("database health check failed: %w", err)
		}
	}

	if deps.Redis {
		if err := redis.HealthCheck(); err != nil {
			return fmt.Errorf("Redis health check failed: %w", err)
		}
	}

	if deps.MongoDB {
		if err := mongodb.HealthCheck(); err != nil {
			return fmt.Errorf("MongoDB health check failed: %w", err)
		}
	}

	return nil
}

// WaitForDependencies 等待外部依赖服务就绪
func WaitForDependencies(deps ServiceDependencies, timeout time.Duration) error {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return fmt.Errorf("timeout waiting for dependencies")
		case <-ticker.C:
			if err := HealthCheck(deps); err == nil {
				return nil
			}
			// 继续等待
		}
	}
}
